#include "TcpPacket.h"
#include "../../../Base/Pause.h"
using mp_base::Pause;

namespace mp_net
{

	TcpPacket::~TcpPacket()
	{
		//Cleanup the packet parts
		while(!TryLock()){Pause(1);}
		while(!m_packetParts.empty())
		{
			vPacketParts::iterator it 
				= m_packetParts.begin();
			delete (*it);
			m_packetParts.erase(it);
		}
		Unlock();
	}

	
	void TcpPacket::GetBuiltPacket(char* packet, uint& size)
	{
		while(!TryLock()){Pause(1);}

		//Calculate the total packet size

		size = HeaderSize();
		for(vPacketParts::iterator it = m_packetParts.begin();
			it < m_packetParts.end(); it++)
		{
			size += 
				(**it).HeaderSize() + 
				(**it).PacketSize();
		}

		//Allocate and build the packet
		
		if ( packet != NULL )
		{
			delete [] packet;
		}

		packet = new char[size];
		uint packetIndex = 0;
		const char* tmp;
		
		// 1 Build Header

		tmp = Header();
		for(uint i = 0; i < HeaderSize(); i++)
		{
			packet[packetIndex++] = tmp[i];
		}

		// 2 Build Packet Parts

		for(vPacketParts::iterator it = m_packetParts.begin();
			it < m_packetParts.end(); it++)
		{
			for(uint i = 0; i < (*it)->HeaderSize(); i++)
				packet[packetIndex++] = (*it)->Header()[i];
			for(uint i = 0; i < (*it)->HeaderSize(); i++)
				packet[packetIndex++] = (*it)->Packet()[i];
		}

		Unlock();
	}

	void TcpPacketPart::GetBuiltPacket(char* packet, uint& size)
	{
		size = HeaderSize() + m_packetSize;
		char* builtPacket = new char[size];
		uint index = 0;

		for(uint i = 0; i < HeaderSize(); i++)
		{
			builtPacket[index++] = Header()[i];
		}
		for(uint i = 0; i < m_packetSize; i++)
		{
			builtPacket[index++] = m_packet[i];
		}
	}

	/*!
	* Builds new packet from packet data.
	*/
	void TcpPacket::BuildFromPacket(const char* packetData)
	{
		while(!TryLock()){Pause(1);}

		Unlock();
	}

	/*!
	* Updates the packet with packet data.
	*/
	void TcpPacket::SyncFromPacket()
	{
		while(!TryLock()){Pause(1);}

		Unlock();
	}

	/*!
	* @brief	Adds a packet part to the data.
	* @note		Shallow Copy
	*/
	void TcpPacket::AddPacketPart(TcpPacketPart* packetPart)
	{
		m_packetParts.push_back(packetPart);
	}

	/*!
	* Removes a packet part from the data.
	*/
	void TcpPacket::RemovePacketPart(
		TcpPacketPart* packetPart, bool deletePart)
	{
		for(vPacketParts::iterator it = m_packetParts.begin();
			it < m_packetParts.end(); it++)
		{
			if ((*it) == packetPart)
			{
				
				if ( deletePart )
					delete packetPart;
				m_packetParts.erase(it);
				break;
			}
		}
	}

}